package org.dftproject.genesis.ui.views;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dftproject.genesis.core.tasks.ITask;
import org.dftproject.genesis.core.tasks.ITaskManagerListener;
import org.dftproject.genesis.core.tasks.TaskManager;
import org.dftproject.genesis.ui.Activator;
import org.dftproject.genesis.ui.tasks.ITaskHandler;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;

public class TaskListView extends ViewPart {

	private static final Log log = LogFactory.getLog(TaskListView.class);

	public static final String ID = TaskListView.class.getName();
	
	private TableViewer viewer;

	@Override
	public void createPartControl(Composite parent) {
		parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

		createContents(parent);
	}

	protected void createContents(Composite parent) {
		TableColumnLayout layout = new TableColumnLayout();

		Composite container = new Composite(parent, SWT.NONE);
		container.setLayout(layout);

		Table table = new Table(container, SWT.FULL_SELECTION);

		TableColumn column = new TableColumn(table, SWT.NONE);
		layout.setColumnData(column, new ColumnWeightData(1));

		viewer = new TableViewer(table);
		viewer.setContentProvider(new IStructuredContentProvider() {
			
			private final ITaskManagerListener listener = new ITaskManagerListener() {

				public void taskAdded(final ITask task) {
					Display.getDefault().asyncExec(new Runnable() {

						public void run() {
							viewer.add(task);
						}
						
					});
				}

				public void taskUpdated(final ITask task) {
					Display.getDefault().asyncExec(new Runnable() {

						public void run() {
							viewer.update(task, null);
						}
						
					});
				}

				public void taskRemoved(final ITask task) {
					Display.getDefault().asyncExec(new Runnable() {

						public void run() {
							viewer.remove(task);
						}
						
					});
				}
				
			};

			public Object[] getElements(Object inputElement) {
				return TaskManager.getDefault().getTasks();
			}

			public void dispose() {
			}

			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
				if (oldInput != null)
					TaskManager.getDefault().removeListener(listener);
				if (newInput != null)
					TaskManager.getDefault().addListener(listener);
			}

		});
		viewer.setLabelProvider(new ITableLabelProvider() {

			public Image getColumnImage(Object element, int columnIndex) {
				return null;
			}

			public String getColumnText(Object element, int columnIndex) {
				if (element instanceof ITask)
					return ((ITask) element).getLabel();
				return "";
			}

			public boolean isLabelProperty(Object element, String property) {
				return false;
			}

			public void addListener(ILabelProviderListener listener) {
			}

			public void removeListener(ILabelProviderListener listener) {
			}

			public void dispose() {
			}

		});
		viewer.addDoubleClickListener(new IDoubleClickListener() {

			public void doubleClick(DoubleClickEvent event) {
				ISelection selection = event.getSelection();
				if (selection instanceof IStructuredSelection) {
					Object element = ((IStructuredSelection) selection).getFirstElement();
					if (element instanceof ITask) {
						ITaskHandler taskHandler = getTaskHandler((ITask) element);
						if (taskHandler != null) {
							taskHandler.handleDoubleClick((ITask) element);
						}
					}
				}
			}

		});
		viewer.setInput(getViewSite());
	}

	protected ITaskHandler getTaskHandler(ITask task) {
		String type = task.getType();
		if (type == null)
			return null;
		
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		IExtensionPoint extensionPoint = registry.getExtensionPoint(Activator.ID, Activator.TASK_HANDLERS_EXTENSION_POINT);
		IExtension[] extensions = extensionPoint.getExtensions();
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
			for (int j = 0; j < configElements.length; j++) {
				if (type.equals(configElements[j].getAttribute("type"))) {
					try {
						Object handler = configElements[j].createExecutableExtension("class");
						if (handler instanceof ITaskHandler)
							return (ITaskHandler) handler;
					} catch (CoreException e) {
						log.error("Failed to create task handler", e);
					}
				}
			}
		}
		
		return null;
	}

	@Override
	public void dispose() {
	}

	@Override
	public void setFocus() {
		viewer.getTable().setFocus();
	}

}
